#ifndef _TWOGRE_POSITION3D_VARIABLE_H_
#define _TWOGRE_POSITION3D_VARIABLE_H_

#include "TwOgrePrerequisites.h"
#include "TwOgreVariable.h"

#include "OgreString.h"
#include "OgreVector3.h"

//#include <cstddef>

// Vector3 structure
struct SVector3
{
    float X;
    float Y;
    float Z;
    SVector3()
    {
        X = 0.0f;
        Y = 0.0f;
        Z = 0.0f;
    }
    SVector3(float x, float y, float z)
    {
        X = x;
        Y = y;
        Z = z;
    }
};
    
namespace TwOgre{
	
    class Position3DParams
    {
    public:
        Position3DParams(const Ogre::String& name)
            : parent_(0)
            , name_(name)
            , label_(Ogre::StringUtil::BLANK)
            , group_(Ogre::StringUtil::BLANK)
            , help_(Ogre::StringUtil::BLANK)
            , type_(TW_TYPE_UNDEF)
            , readOnly_(false)
            , data_(NULL)
            , setCB_(NULL)
            , getCB_(NULL)
            , precision_(2)
            , value_(Ogre::Vector3::ZERO)
        {}
     
        Position3DParams& label(const Ogre::String& varLabel)
        {
            label_ = varLabel;
            return *this;
        }
        Position3DParams& group(const Ogre::String& varGroup)
        {
            group_ = varGroup;
            return *this;
        }
        Position3DParams& help(const Ogre::String& varHelp)
        {
            help_ = varHelp;
            return *this;
        }
        Position3DParams& readOnly(bool varReadOnly)
        {
            readOnly_ = varReadOnly;
            return *this;
        }
        Position3DParams& callback(TwSetVarCallback setter, TwGetVarCallback getter, void* varData)
        {
            setCB_ = setter;
            getCB_ = getter;
            data_ = varData;
            return *this;
        }
        Position3DParams& precision(const int digits)
        {
            precision_ = digits;
            return *this;
        }
        Position3DParams& value(const Ogre::Vector3& vectorVal)
        {
            value_ = vectorVal;
            return *this;
        }
    private:
		Window* parent_;
		Ogre::String name_;
        Ogre::String label_;
        Ogre::String group_;
        Ogre::String help_;
		TwType type_;
        bool readOnly_;
        void* data_;
        TwSetVarCallback setCB_;
        TwGetVarCallback getCB_;
        int precision_;

        Ogre::Vector3 value_;
        
        friend class Window;
		friend class Position3DVariable;		
    };

    class TwOgreExport Position3DVariable : public Variable
	{
	protected:
		Position3DVariable(Window *parent, const Ogre::String& name, bool readOnly, const Ogre::String& label, 
			Ogre::Vector3 value, const Ogre::String& groupName, const Ogre::String& help);
		Position3DVariable(Position3DParams& params);
		~Position3DVariable();

	public:
		Ogre::Vector3 getVector3Value() const;
		void setVector3Value(Ogre::Vector3 value);

	private:
		mutable Ogre::Vector3 mValue;
		SVector3 mSVectorValue;

		friend class Window;
	};
}; // End Namespace

#endif
